#pragma once
#include <iostream>
#include <memory>
#include <unordered_map>
#include "Epoller.hpp"
#include "Connection.hpp"
#include "Log.hpp"

using connection_t = shared_ptr<Connection>;
using namespace Log_Module;
using namespace Epoll_M;

class Reactor
{
    const static int event_num = 64;

public:
    Reactor()
        : _isrunning(false),
          _epoller(make_unique<Epoller>())
    {
        _epoller->Init();
    }
    void Insert_Connection(connection_t conn)
    {
        auto iter = _connections.find(conn->Sockfd());
        if (iter == _connections.end())
        {
            // 1. 把连接，放到unordered_map中进行管理
            _connections.insert(std::make_pair(conn->Sockfd(), conn));
            // 2. 把新插入进来的连接，写透到内核的epoll中
            _epoller->Add(conn->Sockfd(), conn->GetEvents());
            // 3. 设置关联关系，让connection回指当前对象
            conn->setOwner(this);
            LOG(Log_Level::DEBUG) << "add connection success: " << conn->Sockfd();
        }
    }
    // 不是一直都关心写的唤醒，是按需要进行设置
    // 在发送缓冲区满了之后，但是还没有写完时，才需要设置
    // 唤醒写的关心
    void EnableRW(int sockfd, bool readable, bool writable)
    {
        if (is_Connection(sockfd))
        {
            // 修改用户层的connection事件
            uint32_t events = ((readable ? EPOLLIN : 0) | (writable ? EPOLLOUT : 0) | EPOLLET);
            _connections[sockfd]->SetEvents(events);
            // 写透到内核中
            _epoller->Update(sockfd, _connections[sockfd]->GetEvents());
        }
    }

    // 对execpter异常的处理
    void DelConnection(int sockfd)
    {
        if (is_Connection(sockfd))
        {
            // 注意顺序
            _epoller->Delete(sockfd);
            _connections[sockfd]->Close();
            _connections.erase(sockfd); // 键值删除
        }
    }

    // 任务的派发
    void Dispather(int n)
    {
        for (int i = 0; i < n; i++)
        {
            // 开始派发任务
            int sockfd = _revs[i].data.fd;
            int event = _revs[i].events;
            // 将错误统一归到读取或在接受过程处理
            if ((event & EPOLLERR) || (event & EPOLLHUP))
            {
                event = (EPOLLIN | EPOLLOUT);
            }
            if ((event & EPOLLIN) && is_Connection(sockfd))
            {
                _connections[sockfd]->Recver();
            }
            if ((event & EPOLLOUT) && is_Connection(sockfd))
            {
                _connections[sockfd]->Sender();
            }
        }
    }

    void Loop_Once(int timeout)
    {
        int n = _epoller->wait(_revs, event_num, timeout);
        Dispather(n);
    }

    void loop()
    {
        _isrunning = true;
        // int timeout = -1;
        int timeout = 1000;
        while (_isrunning)
        {
            Loop_Once(timeout);
            // 超时管理
            // 简单的,遍历_connections, 判断当前时间 - connection的最近访问时间>XXX
            // 超时了
        }
        _isrunning = false;
    }

    void stop()
    {
        _isrunning = false;
    }
    ~Reactor() {}

private:
    unordered_map<int, connection_t> _connections;
    bool _isrunning;
    unique_ptr<Epoller> _epoller;
    struct epoll_event _revs[event_num];

    bool is_Connection(int sockfd)
    {
        return _connections.find(sockfd) != _connections.end();
    }
};